﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CombineProto
{
    public class CombineProto
    {
        protected List<Message> p_cMessages = new List<Message>();
        protected List<MessageEnum> p_cEnums = new List<MessageEnum>();
        protected List<Message> p_luaMessages = new List<Message>();
        protected List<MessageEnum> p_luaEnums = new List<MessageEnum>();
        protected List<MessageEnum> p_allEnums = new List<MessageEnum>();
        protected List<Message> p_allMessages = new List<Message>();

        protected GenerateConfig p_config;
        public CombineProto()
        {

        }
        public CombineProto(GenerateConfig config)
        {
            p_config = config;
        }
        public void AddCMessage(string name)
        {
            bool flag = false;
            for (int i = 0; i < p_allMessages.Count; i++)
            {
                if (p_allMessages[i].name.Equals(name))
                {
                    flag = true;
                    if (!p_cMessages.Contains(p_allMessages[i]))
                    {
                        p_cMessages.Add(p_allMessages[i]);
                        for (int j = 0; j < p_allMessages[i].dots.Count; j++)
                        {
                            MessageValue d = p_allMessages[i].dots[j];
                            if (!(d.type.Equals("int32") || d.type.Equals("int64") || d.type.Equals("string") || d.type.Equals("float")))
                            {
                                AddCMessage(d.type);
                            }
                        }
                    }
                    break;
                }
            }

            if (!flag)
            {
                for (int i = 0; i < p_allEnums.Count; i++)
                {
                    if (p_allEnums[i].name.Equals(name))
                    {
                        flag = true;
                        if (!p_cEnums.Contains(p_allEnums[i]))
                        {
                            p_cEnums.Add(p_allEnums[i]);
                        }
                        break;
                    }
                }
            }
        }
        public void AddLuaMessage(string name)
        {
            bool flag = false;
            for (int i = 0; i < p_allMessages.Count; i++)
            {
                if (p_allMessages[i].name.Equals(name))
                {
                    flag = true;
                    if (!p_luaMessages.Contains(p_allMessages[i]))
                    {
                        p_luaMessages.Add(p_allMessages[i]);
                        for (int j = 0; j < p_allMessages[i].dots.Count; j++)
                        {
                            MessageValue d = p_allMessages[i].dots[j];
                            if (!(d.type.Equals("int32") || d.type.Equals("int64") || d.type.Equals("string") || d.type.Equals("float")))
                            {
                                AddLuaMessage(d.type);
                            }
                        }
                    }
                    break;
                }
            }

            if (!flag)
            {
                for (int i = 0; i < p_allEnums.Count; i++)
                {
                    if (p_allEnums[i].name.Equals(name))
                    {
                        flag = true;
                        if (!p_luaEnums.Contains(p_allEnums[i]))
                        {
                            p_luaEnums.Add(p_allEnums[i]);
                        }
                        break;
                    }
                }
            }
        }
        public string RunBat(string batPath, string argu)
        {
            using (Process proc = new Process())
            {
                FileInfo file = new FileInfo(batPath);
                proc.StartInfo.Verb = "call";
                proc.StartInfo.FileName = batPath;
                //proc.StartInfo.Arguments = "< nul";
                proc.StartInfo.Arguments = string.IsNullOrEmpty(argu) ? "< null" : argu;
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.WorkingDirectory = file.Directory.FullName;
                proc.EnableRaisingEvents = true;
                proc.StartInfo.CreateNoWindow = true;
                StringBuilder errorSb = new StringBuilder();
                //StringBuilder outputSb = new StringBuilder();
                proc.ErrorDataReceived += (sender, args) => errorSb.Append(args.Data);
                //proc.OutputDataReceived += (sender, args) => outputSb.AppendLine(args.Data);
                proc.Start();
                //proc.BeginOutputReadLine();
                proc.BeginErrorReadLine();
                proc.StandardInput.WriteLine("exit");
                try
                {
                    //proc.WaitForInputIdle();
                    proc.StandardInput.WriteLine();
                }
                catch (Exception)
                {
                    throw;
                }
                //proc.WaitForExit();
                proc.StandardOutput.ReadToEnd();
                if (errorSb.Length > 0)
                {
                    return errorSb.ToString();
                }
            }
            return string.Empty;
        }
        public void AynalizeProto()
        {
            string protoPath = Path.Combine(System.Environment.CurrentDirectory, p_config.sourceProtoRelatePath);//QuickUnity.DirectorySetting.ProtoExportPath();
            DirectoryInfo dir = new DirectoryInfo(protoPath);

            FileInfo[] files = dir.GetFiles("*.proto", SearchOption.AllDirectories);
            if (files.Length == 0)
            {
                //EditorUtility.DisplayDialog("协议", "Proto文件夹为空！!！!", "关闭");
                return;
            }

            List<string> textLines = new List<string>();
            for (int i = 0; i < files.Length; i++)
            {
                using (StreamReader r = files[i].OpenText())
                {
                    string text = r.ReadToEnd();
                    text = text.Replace("\r", "");
                    string[] ts = text.Split('\n');
                    for (int j = 0; j < ts.Length; j++)
                    {
                        if (!(ts[j].Contains("import") || ts[j].Contains("package " + p_config.packageName + ";") || ts[j].Equals("")))
                        {
                            if (ts[j].Contains("//"))
                            {
                                var ind = ts[j].IndexOf("//");
                                if (ind >= 0)
                                {
                                    ts[j] = ts[j].Substring(0, ind);
                                }
                                else
                                {
                                    throw new Exception("// out index  " + ts[j]);
                                }
                            }
                            if (!string.IsNullOrEmpty(ts[j]))
                            {
                                textLines.Add(ts[j]);
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < textLines.Count;)
            {
                if (textLines[i].Contains("enum"))
                {
                    MessageEnum e = new MessageEnum();
                    string str = textLines[i];
                    string[] tempStr = str.Split(' ');
                    int tempStrCount = 0;
                    for (int j = 0; j < tempStr.Length; j++)
                    {
                        string temp = tempStr[j].Replace(" ", "").Replace("\t", "");
                        if (!string.IsNullOrEmpty(temp))
                        {
                            tempStrCount++;
                        }
                        if (tempStrCount == 2)
                        {
                            e.name = temp.Replace("{", "");
                            break;
                        }
                    }
                    bool multiLineFlag = false;
                    for (int j = i + 1; j < textLines.Count; j++)
                    {
                        if (textLines[j].Contains("}"))
                        {
                            i = j + 1;
                            break;
                        }
                        bool endFlag = false;
                        string content = textLines[j];
                        if (content.Contains("}"))
                        {
                            endFlag = true;
                            content = content.Replace("}", "");
                        }
                        if (content.Contains("//"))
                        {
                            content = content.Substring(0, content.IndexOf("//"));
                        }

                        if (content.Contains("/*"))
                        {
                            multiLineFlag = true;
                        }
                        if (content.Contains("*/"))
                        {
                            multiLineFlag = false;
                            continue;
                        }
                        if (multiLineFlag)
                        {
                            continue;
                        }
                        content = content.Replace("{", "");
                        if (string.IsNullOrEmpty(content.Replace(" ", "").Replace("\t", "")))
                        {
                            if (endFlag)
                            {
                                i = j + 1;
                                break;
                            }
                            else
                            {
                                continue;
                            }
                        }

                        EnumValue d = new EnumValue();
                        string[] tempStr2 = content.Split('=');
                        tempStrCount = 0;
                        for (int k = 0; k < tempStr2.Length; k++)
                        {
                            string temp = tempStr2[k].Replace(" ", "").Replace("\t", "");
                            if (!string.IsNullOrEmpty(temp))
                            {
                                tempStrCount++;
                                if (tempStrCount == 1)
                                {
                                    d.name = temp;
                                    if (string.IsNullOrEmpty(p_config.scCmdPreExtension) || string.IsNullOrEmpty(p_config.csCmdPreExtension))
                                    {
                                        d.msgName = temp;
                                    }
                                    else
                                    {
                                        d.msgName = temp.Replace(p_config.scCmdPreExtension, "").Replace(p_config.csCmdPreExtension, "");
                                    }
                                    //d.msgName = temp.Replace(p_config.scCmdPreExtension, "").Replace(p_config.csCmdPreExtension, "");
                                }
                                else if (tempStrCount == 2)
                                {
                                    d.value = temp;
                                    break;
                                }
                            }
                        }
                        d.value = tempStr2[1].Replace(" ", "").Replace(";", "");
                        if (d.value.Contains("["))
                        {
                            d.value = d.value.Substring(0, d.value.IndexOf("["));
                        }
                        e.dots.Add(d);
                        if (endFlag)
                        {
                            i = j + 1;
                            break;
                        }
                    }
                    p_allEnums.Add(e);
                }
                else if (textLines[i].Contains("message"))
                {
                    Message m = new Message();
                    string str = textLines[i];
                    if (str.Contains("//"))
                    {
                        str = str.Substring(0, str.IndexOf("//"));
                    }

                    string[] tempStr = str.Split(' ');
                    int tempStrCount = 0;
                    for (int j = 0; j < tempStr.Length; j++)
                    {
                        string temp = tempStr[j].Replace(" ", "").Replace("\t", "");
                        if (!string.IsNullOrEmpty(temp))
                        {
                            tempStrCount++;
                        }
                        if (tempStrCount == 2)
                        {
                            m.name = temp.Replace("{", "");
                            break;
                        }
                    }

                    bool multiLineFlag = false;
                    for (int j = i + 1; j < textLines.Count; j++)
                    {
                        bool endFlag = false;
                        string content = textLines[j];
                        if (content.Contains("}"))
                        {
                            endFlag = true;
                            content = content.Replace("}", "");
                        }

                        if (content.Contains("//"))
                        {
                            content = content.Substring(0, content.IndexOf("//"));
                        }

                        if (content.Contains("/*"))
                        {
                            multiLineFlag = true;
                        }
                        if (content.Contains("*/"))
                        {
                            multiLineFlag = false;
                            continue;
                        }
                        if (multiLineFlag)
                        {
                            continue;
                        }
                        content = content.Replace("{", "");
                        if (string.IsNullOrEmpty(content.Replace(" ", "").Replace("\t", "")))
                        {
                            if (endFlag)
                            {
                                i = j + 1;
                                break;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        MessageValue d = new MessageValue();
                        string[] tempStr2 = content.Split('=');
                        string[] tempStr3 = tempStr2[0].Split(' ');
                        tempStrCount = 0;
                        for (int k = 0; k < tempStr3.Length; k++)
                        {
                            string temp = tempStr3[k].Replace(" ", "");
                            if (!string.IsNullOrEmpty(temp))
                            {
                                tempStrCount++;
                                if (tempStrCount == 1)
                                {
                                    d.tag = temp;
                                }
                                else if (tempStrCount == 2)
                                {
                                    d.type = temp;
                                }
                                else if (tempStrCount == 3)
                                {
                                    d.name = temp;
                                    break;
                                }
                            }
                        }
                        if (tempStr2.Length < 2)
                        {
                            throw new Exception(string.Concat(tempStr2));
                        }
                        d.value = tempStr2[1].Replace(" ", "").Replace(";", "");
                        if (d.value.Contains("["))
                        {
                            d.value = d.value.Substring(0, d.value.IndexOf("["));
                        }
                        m.dots.Add(d);
                        if (endFlag)
                        {
                            i = j + 1;
                            break;
                        }
                    }
                    p_allMessages.Add(m);
                }
                else
                {
                    i++;
                }
            }
        }
        public void SaveFile(string path, string content)
        {
            FileInfo pathInfo = new FileInfo(path);
            if (!pathInfo.Directory.Exists)
            {
                pathInfo.Directory.Create();
            }
            using (FileStream fs = new FileStream(path, FileMode.Create))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    sw.Write(content);
                }
            }
        }
    }
}
